package com.anycc.cloud.core.service.impl;

import com.anycc.cloud.core.dto.Breadcrumb;
import com.anycc.cloud.core.dto.Menu;
import com.anycc.cloud.core.entity.Account;
import com.anycc.cloud.core.entity.Module;
import com.anycc.cloud.core.entity.Role;
import com.anycc.cloud.core.repository.ModuleRepository;
import com.anycc.cloud.core.repository.RoleRepository;
import com.anycc.cloud.core.service.MenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

import static com.anycc.cloud.common.constant.CacheNameConstant.FIELD_CACHE_BREADCRUMB;
import static com.anycc.cloud.common.constant.CacheNameConstant.FIELD_CACHE_MENU;

/**
 * menu service impl
 */
@Service
public class MenuServiceImpl implements MenuService {
    @Autowired
    private ModuleRepository moduleRepository;
    @Autowired
    private RoleRepository roleRepository;


    @Override
    @Cacheable(value = FIELD_CACHE_MENU, key = "#username+'_'+#selectedSN")
    public List<Menu> makeMenu(String username, Account account, String selectedSN) {
        List<Module> beforeHandleModules = new ArrayList<>();
        Optional.ofNullable(account.getRoles()).ifPresent(roles ->
                roles.forEach(role ->
                        Optional.ofNullable(role.getPermissions()).ifPresent(permissions ->
                                permissions.forEach(permission -> {
                                    if (permission.getModule() != null && !beforeHandleModules.contains(permission.getModule())) {
                                        beforeHandleModules.add(permission.getModule());
                                    }
                                })
                        )
                )
        );
        return buildMenus(beforeHandleModules, selectedSN);
    }

    @Override
    @Cacheable(value = FIELD_CACHE_BREADCRUMB, key = " #selectedSN")
    public List<Breadcrumb> makeBreadcrumb(String selectedSN) {
        Module module = moduleRepository.findBySn(selectedSN.toUpperCase());
        if (module == null) {
            return new ArrayList<>();
        } else {
            return buildBreadCrumb(module);
        }
    }

    @Override
    public List<String> findFullPermissionString(List<String> roleNames) {
        List<String> fullPermissionStrings = new ArrayList<>();
        roleNames.forEach(roleName -> {
            Role role = roleRepository.findBySn(roleName);
            role.getPermissions().forEach(permission ->
                    fullPermissionStrings.add(StringUtils.replace(permission.getModule().getSn() + ":" + permission.getSn(), ":", "/"))
            );
        });
        return fullPermissionStrings;
    }

    private List<Menu> buildMenus(List<Module> moduleList, String selectedSN) {
        List<Module> rootModules = moduleList.stream().filter(module -> module.getParent() == null).sorted(
                Comparator.comparing(Module::getPriority)).collect(Collectors.toList());
        return rootModules.stream().map(rootModule -> buildMenu(rootModule, moduleList, selectedSN)).collect(Collectors.toList());
    }

    private Menu buildMenu(Module rootModule, List<Module> moduleList, String selectedSN) {
        Menu menu = new Menu(rootModule.getName(), rootModule.getIcon(), rootModule.getSn(), rootModule.getTarget(), buildUrlBySn(rootModule.getSn()), selectedSN.equals(rootModule.getSn()));
        List<Menu> menuChildren = new ArrayList<>();
        moduleList.stream().filter(module -> rootModule.getChildren().contains(module)).sorted(Comparator.comparing(Module::getPriority)).collect(Collectors.toList()).forEach(module ->
                menuChildren.add(buildMenu(module, moduleList, selectedSN))
        );
        menu.setChildren(menuChildren);
        return menu;

    }

    private String buildUrlBySn(String sn) {
        Assert.notNull(sn, "模块SN不能为空");
        String url = sn.replace(":", "/");
        url = url + "/" + "index.html";
        return url.startsWith("/") ? StringUtils.lowerCase(url) : StringUtils.lowerCase("/" + url);
    }

    private List<Breadcrumb> buildBreadCrumb(Module module) {
        List<Breadcrumb> breadcrumbs = new ArrayList<>();
        while (module != null) {
            breadcrumbs.add(new Breadcrumb(module));
            module = module.getParent();
        }
        Collections.reverse(breadcrumbs);
        return breadcrumbs;
    }


}
